<?php

//Memcache开关 1 使用, 0 不使用
define('MEMCACHE_MODE', 1);

class MemcacheGroupConn {

	/**
    * 构造函数，进行MEMCACHE服务器连接 
    * @param $servers - 多个cache server的地址数组 
    */   
	var $connections;
	var $servers;

	public function __construct() {
		$this->servers=array(
		array('host' => 'localhost', 'port' => 11211),
		array('host' => 'localhost', 'port' => 11212)
		);

		//		$this->servers=array(array('host' => 'dc4.cyworld.com.cn', 'port' => 11211),array('host' => 'dc1.cyworld.com.cn', 'port' => 11211),array('host' => 'dc1.cyworld.com.cn', 'port' => 11212),array('host' => 'dc4.cyworld.com.cn', 'port' => 11212));
		$this->connections = array();
	}

	/**
    * 根据传入的参数决定，连接哪个MEMCACHE服务器
    *
    * @param $key
    * @return 如果没有MEMCAHCE连接则返回FALSE，否则返回指定的连接
    */
	public function getMemConnWithKey($num) {
		$server=$this->servers[$num];
		try{
			if ($this->connections[$num]){
				return $this->connections[$num];
			}
			else {
				$conn = @memcache_connect($server['host'], $server['port']);
				if (!$conn) throw new Exception($error);
				else{
					$this->connections[$num] = $conn;
					return $conn;
				}
			}
		}
		catch(Exception $e){
		}
		return false;
	}

	/**
    * 根据传入的参数决定，连接哪个MEMCACHE服务器
    *
    * @param unknown_type $key
    * @return 如果没有MEMCAHCE连接则返回FALSE，否则返回指定的连接
    */
	public function getAllMemConn() {
		$conns=array();
		$error="";
		$j=0;
		for ($i = 0, $n = count($this->servers); $i < $n; $i++) {

			$server = $this->servers[$i];
			try{
				$conn = @memcache_connect($server['host'], $server['port']);
				if (!$conn) throw new Exception($error);
				else
				{
					$conns[$j] = $conn;
					$j++;
				}
			}
			catch(Exception $e){
			}
		}
		return $conns;
	}

	/**
    * 根据传入的参数决定，连接哪个MEMCACHE服务器
    *
    * @param unknown_type $key
    * @return 如果没有MEMCAHCE连接则返回FALSE，否则返回指定的连接
    */
	public function getConnForKey($key) {
		$hashCode = 0;
		if (strlen($key)>12){
			$hashCode=0;
			//计算是否相册频道的KEY，所有A开头的，并且KEY的长度超过12的都放在DC1的11212服务器上
			$cyid=substr($key,-10);
			$albumkey=substr($key,0,1);
			if ($albumkey=="A"||$albumkey=="C"||$albumkey=="X"){
				$hashCode=3;
			}
			else{
				if ($cyid<=2004510000)
				$hashCode=0;
				else
				$hashCode=4;
			}
		}
		else{
			$hashCode=1;
			$cyid=substr($key,2,10);
			if ($cyid<=2003510000){
				$hashCode=1;
			}
			else if (($cyid<=2005510000)&&($cyid>2003510000)){
				$hashCode=2;
			}
			else{
				$hashCode=5;
			}
		}

		/*
		for ($i = 0, $len = strlen($key); $i < $len; $i++) {
		$hashCode = (int)(($hashCode*33)+ord($key[$i])) & 0x7fffffff;
		}
		*/
		if (($ns = count($this->servers)) > 0) {
			$c=$hashCode%$ns;
			return $this->getMemConnWithKey($c);
		}
		return false;
	}

	/**
    * 是否输出调试信息
    *
    * @param unknown_type $on_off
    * @return true or false
    */
	public function debug($on_off) {
		$result = false;
		$connects=$this->getAllMemConn();
		for ($i = 0; $i < count($connects); $i++) {
			if ($connects[$i]->debug($on_off)) $result = true;
		}
		return $result;
	}

	/**
    * 使所有缓存的数据失效；这个失效并不会清空内存，只是被占用的内存会被新的内容覆盖
    *
    * @return true or false
    */
	public function flush() {
		$result = false;
		$connects=$this->getAllMemConn();
		for ($i = 0; $i < count($connects); $i++) {
			if ($connects[$i]->flush()) $result = true;
		}
		return $result;
	}

	/**
    * 取得各个服务器的状态信息，并保存在数组中返回
    *
    * @return 返回array
    */
	/*
	public function getStatus() {
	$statusArr="";
	for ($i = 0; $i < count($this->connections); $i++) {
	$statusArr[$i]= ($this->connections[$i]->getStats());
	}
	return $statusArr;
	}
	*/
	public function getStatus() {
		$connects=$this->getAllMemConn();
		$statusArr="";
		for ($i = 0; $i < count($connects); $i++) {
			$statusArr[$i]= ($connects[$i]->getStats());
		}
		return $statusArr;
	}

	/**
    * 取得某个KEY的缓存内容
    *
    * @param String_type $key
    * @return 如果没有缓存内容，则会返回false
    */
	public function get($key) {
		if (is_array($key)) {
			$dest = array();
			foreach ($key as $subkey) {
				$val = $this->get($subkey);
				if (!($val === false)) {
					$dest[$subkey] = $val;
				}
			}
			return $dest;
		} else {
			//ScriptTime::startDebug('memcached');

			if ($this->getConnForKey($key)) {
				$value = $this->getConnForKey($key)->get($key);

				if (false === $value) {
					//ScriptTime::endDebug('memcached', 'miss '. $key);
				} else {
					//ScriptTime::endDebug('memcached', 'got '. $key);
				}
			} else {
				$value = false;

				//ScriptTime::endDebug('memcached', 'discon '. $key);
			}

			return $value;
		}
	}

	/**
    * 增加缓存的内容
    *
    * @param unknown_type $key 内容关键字
    * @param unknown_type $var 要存储的内容，可以是字符串或者数组等
    * @param unknown_type $compress 是否压缩，0表示不压缩，MEMCACHE_COMPRESSED 表示要压缩
    * @param unknown_type $expire 失效时间，0表示永不失效，但是如果服务器内存不够，将根据先进先出的原则进行失效
    * @return 成功返回true 否则返回false
    */
	public function set($key, $var, $compress=0, $expire=0) {
		//			$this->addKeyFromArray($key);
		if ($this->getConnForKey($key)) {
			return $this->getConnForKey($key)->set($key, $var, $compress, $expire);
		}
	}

	/**
    * 往内存中增加内容，用法同set
    *
    * @param unknown_type $key
    * @param unknown_type $var
    * @param unknown_type $compress
    * @param unknown_type $expire
    * @return unknown
    */
	public function add($key, $var, $compress=0, $expire=0) {
		if ($this->getConnForKey($key)) {
			return $this->getConnForKey($key)->add($key, $var, $compress, $expire);
		}
	}

	/**
    * 替换已经存在的缓存中某个KEY的内容
    *
    * @param unknown_type $key 要替代的KEY的值
    * @param unknown_type $var 要替代的内容
    * @param unknown_type $compress 压缩标志
    * @param unknown_type $expire 失效时间（秒为单位）
    * @return unknown
    */
	public function replace($key, $var, $compress=0, $expire=0) {
		if ($this->getConnForKey($key)) {
			return $this->getConnForKey($key)->replace($key, $var, $compress, $expire);
		}
	}

	/**
    * 删除缓存中的内容
    *
    * @param unknown_type $key 要删除的KEY
    * @param unknown_type $timeout 延期时间，如果为0表示立即删除
    * @return unknown
    */
	public function delete($key, $timeout=0) {
		if ($this->getConnForKey($key)) {
			return $this->getConnForKey($key)->delete($key, $timeout);
		}
	}

	/**
    * 为某个KEY值里面的内容，增加$value，只有原来的value为数值的时候才可以相加，
    * 否则原来的值会被要增加的值覆盖
    *
    * @param unknown_type $key 
    * @param unknown_type $value 增加的量
    * @return unknown
    */
	public function increment($key, $value=1) {
		if ($this->getConnForKey($key))
		return $this->getConnForKey($key)->increment($key, $value);
	}

	/**
    * 为某个KEY值里面的内容，减去$value，只有原来的value为数值的时候才可以相加
    * 修改后的值要保证>0
    *
    * @param unknown_type $key 要修改的关键字
    * @param unknown_type $value 要减去的量
    * @return unknown
    */
	public function decrement($key, $value=1) {
		if ($this->getConnForKey($key))
		return $this->getConnForKey($key)->decrement($key, $value);
	}
	//test function
	public function getConn() {
		return $this->servers;
	}


	/**
    * 增加cache里面存放的某个key的值
    *
    * @param unknown_type $key
    * @return 不返回数据
    */

/*	public function addKeyFromArray($key) {
		$cyidArray=$this->get("CYIDKEYLIST");
		if ($cyidArray=="") {
			$cyidArray=Array("0");
			$this->set("CYIDKEYLIST",$cyidArray,0,0);
		}
		if ($key!="CYIDKEYLIST") {
			array_push($cyidArray,$key);
			$this->replace("CYIDKEYLIST",$cyidArray,0,0);
		}
	}
*/

	/**
	 * 删除数组中某个key
	 *
	 * @param unknown_type $array ：要操作的数组
	 * @param unknown_type $indice ：要删除的key位置
	 * @return Array
	 */
/*	public function eliminarElementoArreglo ($array, $indice) {
		if (array_key_exists($indice, $array)) {
			$temp = $array[0];
			$array[0] = $array[$indice];
			$array[$indice] = $temp;
			array_shift($array);

			for ($i = 0 ; $i < $indice ; $i++) {
				$dummy = $array[$i];
				$array[$i] = $temp;
				$temp = $dummy;
			}
		}
		return $array;
	}*/

}
?>